home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Aminet 16
/
Aminet 16 (1996)(GTI - Schatztruhe)[!][Dec 1996].iso
/
Aminet
/
comm
/
term
/
term_source.lha
/
Extras
/
Source
/
term-source.lha
/
Chat.c
< prev
next >
Wrap
C/C++ Source or Header
|
1996-10-20
|
8KB
|
450 lines
/*
** Chat.c
**
** Chat support code
**
** Copyright © 1990-1996 by Olaf `Olsen' Barthel
** All Rights Reserved
**
** :ts=4
*/
#ifndef _GLOBAL_H
#include "Global.h"
#endif
/* Maximum number of characters to enter per line */
#define CHAT_LINE_SIZE 512
/* Local data */
STATIC struct List *ChatList;
STATIC struct Node *ChatNode;
STATIC STRPTR ChatBuffer,
ChatUndo,
ChatWork,
ChatTemp;
STATIC ULONG ChatPosition;
STATIC Object *ChatGadget;
STATIC BOOL ChatWasActive;
/* HideChatGadget():
*
* Remove the chat gadget, but don't free the buffers.
*/
VOID
HideChatGadget()
{
if(ChatGadget)
{
GetAttr(STRINGA_BufferPos,ChatGadget,&ChatPosition);
RemoveGList(Window,(struct Gadget *)ChatGadget,1);
DisposeObject(ChatGadget);
ChatGadget = NULL;
}
}
/* DeleteChatGadget():
*
* Remove the chat gadget, also take care of the buffers.
*/
VOID
DeleteChatGadget()
{
HideChatGadget();
FreeVecPooled(ChatBuffer);
ChatBuffer = NULL;
DeleteList(ChatList);
ChatList = NULL;
}
/* UpdateChatGadget():
*
* Redraw the chat gadget imagery.
*/
VOID
UpdateChatGadget()
{
if(ChatGadget)
{
struct RastPort *RPort;
LONG Left,Right,Top;
RPort = Window->RPort;
/* Draw the separator bar */
if(StatusWindow || Config->ScreenConfig->StatusLine == STATUSLINE_DISABLED)
Top = UserFontHeight;
else
Top = StatusDisplayHeight + UserFontHeight;
Top = Window->Height - (Window->BorderBottom + Top + 2);
Left = Window->BorderLeft;
Right = Window->Width - (Window->BorderRight + 1);
SetAPen(RPort,Pens[SHADOWPEN]);
RectFill(RPort,Left,Top,Right,Top);
Top++;
SetAPen(RPort,Pens[SHINEPEN]);
RectFill(RPort,Left,Top,Right,Top);
/* Redraw the gadget */
RefreshGList((struct Gadget *)ChatGadget,Window,NULL,1);
}
}
/* ActivateChat(BOOL Reactivate):
*
* Activate the chat gadget.
*/
VOID
ActivateChat(BOOL Reactivate)
{
if(ChatGadget)
{
if(Reactivate)
Reactivate = ChatWasActive;
else
Reactivate = TRUE;
if(Reactivate)
ActivateGadget((struct Gadget *)ChatGadget,Window,NULL);
}
}
/* CreateChatGadget():
*
* Create the chat gadget and add it to the main window.
*/
BOOL
CreateChatGadget()
{
ChatWasActive = TRUE;
/* Allocate the history list */
if(!ChatList)
{
if(!(ChatList = CreateList()))
return(FALSE);
ChatNode = NULL;
}
/* Allocate the undo/work/editing buffers */
if(!ChatBuffer)
{
if(!(ChatBuffer = (STRPTR)AllocVecPooled(5 * CHAT_LINE_SIZE,MEMF_ANY | MEMF_CLEAR)))
{
DeleteChatGadget();
return(FALSE);
}
else
{
ChatUndo = ChatBuffer + CHAT_LINE_SIZE;
ChatWork = ChatUndo + CHAT_LINE_SIZE;
ChatTemp = ChatWork + CHAT_LINE_SIZE;
}
}
/* Finally create the gadget */
if(!ChatGadget)
{
STATIC struct Hook ChatHook;
LONG Bottom = Window->BorderBottom + UserFontHeight - 1;
InitHook(&ChatHook,(HOOKFUNC)CommonEditRoutine,NULL);
if(!StatusWindow && Config->ScreenConfig->StatusLine != STATUSLINE_DISABLED && !Config->ScreenConfig->SplitStatus)
Bottom += StatusDisplayHeight;
if(!(ChatGadget = NewObject(NULL,STRGCLASS,
GA_Left, Window->BorderLeft,
GA_Height, UserFontHeight,
GA_RelBottom, -Bottom,
GA_RelWidth, -(Window->BorderLeft + Window->BorderRight),
GA_TabCycle, FALSE,
GA_ID, CHAT_GadgetID,
GA_RelVerify, TRUE,
GA_Immediate, TRUE,
STRINGA_TextVal, ChatBuffer,
STRINGA_MaxChars, CHAT_LINE_SIZE-1,
STRINGA_Buffer, ChatBuffer,
STRINGA_BufferPos, ChatPosition,
STRINGA_UndoBuffer, ChatUndo,
STRINGA_WorkBuffer, ChatWork,
STRINGA_NoFilterMode, TRUE,
STRINGA_EditHook, &ChatHook,
/* NOTE: This should really look like below, */
/* according to the BOOPSI documentation. */
/* Even worse, the pen numbers are in reality */
/* truncated to a maximum of colour # 15. */
/* STRINGA_Pens, ((LONG)Pens[BACKGROUNDPEN] << 16) | Pens[TEXTPEN], */
/* STRINGA_ActivePens, ((LONG)Pens[BACKGROUNDPEN] << 16) | Pens[TEXTPEN], */
STRINGA_Pens, (Pens[BACKGROUNDPEN] << 8) | Pens[TEXTPEN],
STRINGA_ActivePens, (Pens[BACKGROUNDPEN] << 8) | Pens[TEXTPEN],
TAG_DONE)))
{
DeleteChatGadget();
return(FALSE);
}
else
AddGList(Window,(struct Gadget *)ChatGadget,(UWORD)~0,1,NULL);
}
return(TRUE);
}
/* HandleChatGadget(UWORD GadgetCode):
*
* Process the input forwarded by the chat line gadget.
*/
VOID
HandleChatGadget(UWORD GadgetCode)
{
BOOL Activate,NeedChange,AddIt;
UWORD Code,Qualifier;
Activate = TRUE;
NeedChange = FALSE;
Code = GadgetCode & 0xFF;
Qualifier = GadgetCode >> 8;
switch(Qualifier)
{
case 0xFF:
switch(Code)
{
case CONTROL_('S'):
case CONTROL_('Q'):
ChatTemp[0] = Code;
SendInputTextBuffer(ChatTemp,1,TRUE,TRUE);
break;
case '\r':
LimitedStrcpy(CHAT_LINE_SIZE,ChatTemp,ChatBuffer);
/* Add the line unless it is already in the history list. */
AddIt = TRUE;
if(ChatNode)
{
if(!Stricmp(ChatNode->ln_Name,ChatTemp))
AddIt = FALSE;
}
if(AddIt)
{
struct Node *Node;
if(Node = CreateNode(ChatTemp))
AddTail(ChatList,Node);
}
ChatNode = NULL;
NeedChange = TRUE;
LimitedStrcat(CHAT_LINE_SIZE,ChatTemp,"\\r");
SerialCommand(ChatTemp);
break;
case '\n':
Activate = FALSE;
break;
}
break;
default:
/* Clear the history list when pressing Amiga+Del/Amiga+Backspace */
if((Qualifier & (AMIGARIGHT | AMIGALEFT)) && (Code == DEL_CODE || Code == BACKSPACE_CODE))
{
FreeList(ChatList);
ChatNode = NULL;
NeedChange = TRUE;
break;
}
/* This looks like a function key. Send the corresponding macro. */
if(Code >= F01_CODE && Code <= F10_CODE)
{
STRPTR String;
LONG Index;
Index = Code - F01_CODE;
/* Pick the right macro */
if(Qualifier & CONTROL_KEY)
String = MacroKeys->Keys[3][Index];
else
{
if(Qualifier & ALT_KEY)
String = MacroKeys->Keys[2][Index];
else
{
if(Qualifier & SHIFT_KEY)
String = MacroKeys->Keys[1][Index];
else
String = MacroKeys->Keys[0][Index];
}
}
/* Anything to do? */
if(String[0])
{
/* This should really insert the macro at the current
* cursor position, but due to some strange reasons
* we can't get the position reliably.
*/
LimitedStrcpy(CHAT_LINE_SIZE,ChatTemp,ChatBuffer);
LimitedStrcat(CHAT_LINE_SIZE,ChatTemp,String);
SetGadgetAttrs((struct Gadget *)ChatGadget,Window,NULL,
STRINGA_TextVal, ChatTemp,
STRINGA_BufferPos, strlen(ChatTemp),
TAG_DONE);
}
break;
}
/* The user pressed the cursor-up key to
* scroll through the command history.
*/
if(Code == CURSORUP)
{
/* Shift key: jump to first command
* history entry.
*/
if(Qualifier & SHIFT_KEY)
{
NeedChange = TRUE;
if(!IsListEmpty(ChatList))
ChatNode = ChatList->lh_Head;
else
ChatNode = NULL;
}
else
{
if(ChatNode)
{
if(ChatNode->ln_Pred->ln_Pred)
{
NeedChange = TRUE;
ChatNode = ChatNode->ln_Pred;
}
}
else
{
if(!IsListEmpty(ChatList))
{
NeedChange = TRUE;
ChatNode = ChatList->lh_TailPred;
}
}
}
}
/* The user pressed the cursor-down key to
* scroll through the command history.
*/
if(Code == CURSORDOWN)
{
NeedChange = TRUE;
/* Shift key: jump to last command
* history entry.
*/
if(Qualifier & SHIFT_KEY)
{
if(!IsListEmpty(ChatList))
ChatNode = ChatList->lh_TailPred;
else
ChatNode = NULL;
}
else
{
if(ChatNode)
{
if(ChatNode->ln_Succ->ln_Succ)
ChatNode = ChatNode->ln_Succ;
else
ChatNode = NULL;
}
}
}
break;
}
/* Check if we have to update the string gadget contents. */
if(NeedChange)
{
SetGadgetAttrs((struct Gadget *)ChatGadget,Window,NULL,
STRINGA_TextVal,ChatNode ? ChatNode->ln_Name : "",
TAG_DONE);
}
ChatWasActive = Activate;
if(Activate)
ActivateGadget((struct Gadget *)ChatGadget,Window,NULL);
}
/* MarkChatGadgetAsActive():
*
* Remember that the chat gadget was activated.
*/
VOID
MarkChatGadgetAsActive()
{
ChatWasActive = TRUE;
}